﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace ops_client
{

    public partial class Form1 : Form
    {
        #region 变量
        /// <summary>
        /// MQTT帮助类
        /// </summary>
        MQTTHelper _MQTTHelper = new MQTTHelper();
        string client_id = null;
        List<Device> DeviceList = new List<Device>();

        #endregion 变量

        public Form1()
        {
            InitializeComponent();
            textBox_server_ip.Text = this.txtIP.Text;
        }

        private void AddDevice(string DUID)
        {
            if (!string.IsNullOrEmpty(DUID))
            { 
                if (online_dev_list.Items.Contains(DUID))
                {
                    Trace_log("相同的设备ID，忽略");
                }
                else
                {
                    Trace_log("Add " + DUID);
                    this.online_dev_list.Items.Add(DUID);
                }
            }
            online_dev_list.SelectedIndex = 0;
        }

        #region 方法
        /// <summary>
        /// 处理逻辑-展示Log
        /// </summary>
        /// <param name="obj"></param>
        private void onMQMessage(ResultData_MQTT mqMsg)
        {
            this.Invoke(new Action(() =>
            { 
                String Topic = mqMsg.ResultObject1;
                String Message = mqMsg.ResultObject2;
                if (string.IsNullOrEmpty(Topic))
                    return;
                Trace_log("Topic:" + Topic);
                Trace_log("MSG:" + Message);
                if (Topic.Contains("bridgeinfo"))
                {
                    BridgeInfo json =  JsonConvert.DeserializeObject<BridgeInfo>(Message);
                    if( json.server_port != 0 && !string.IsNullOrEmpty(json.server_ip) )
                    {
                        textBox_server_port.Text = json.server_port.ToString();
                        textBox_server_ip.Text = json.server_ip;
                    }
                }
                else if (Topic.Contains("info") || Topic.Contains("online"))
                {
                    try
                    { 
                        DeviceInfo info = JsonConvert.DeserializeObject<DeviceInfo> (Message);
                        if (!string.IsNullOrEmpty(info.data.DUID))
                        {
                            Device device = info.data;
                            if (!DeviceList.Contains(device))
                                DeviceList.Add(device);
                            AddDevice(info.data.DUID); 
                        } 
                    }catch(Exception ex)
                    {
                        Trace_log("Error:" + ex.StackTrace);
                    }
                }
                else if (Topic.Contains("status"))
                { 
                }  
            }));
        }
        #endregion 方法

        private void Trace_log(string text)
        {
            if (!text.EndsWith("\r\n"))
                text += "\r\n";
            textBoxLog.AppendText(DateTime.Now.ToString("[HH:mm:ss.fff]") + text  );
            textBoxLog.ScrollToCaret();
        }
           
        public static string GenerateRandomID()
        {
            const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            var random = new Random();
            var result = new string(
                Enumerable.Repeat(chars, 8)
                          .Select(s => s[random.Next(s.Length)])
                          .ToArray());

            return result;
        }
 
 
        /// <summary>
        /// 连接MQTT服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_start_Click(object sender, EventArgs e)
        {
            string uName = txtName.Text;
            string uPwd = txtPassword.Text; 
            string ipStr = txtIP.Text.Trim();
            string portStr = txtPort.Text.Trim();
            if (ipStr.Equals("47.116.13.41"))
            {
                uName = "transpeed";
                uPwd = "transpeed@runwell_2023";
            }
            if (string.IsNullOrEmpty(ipStr))
            {
                MessageBox.Show("IP地址不可为空");
                return;
            }
            if (string.IsNullOrEmpty(portStr))
            {
                MessageBox.Show("端口不可为空");
                return;
            }
            int port = Convert.ToInt32(portStr);
            Action<ResultData_MQTT> callback = onMQMessage;
            await _MQTTHelper.CreateMQTTClientAndStart(ipStr, port, uName, uPwd, callback);

            String DevType = dev_type.Text;
            client_id = GenerateRandomID();
            String Topic = String.Format("iot/{0}/bridgeinfo", client_id);
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/{0}/status", client_id);
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/{0}/response", client_id);
            SubsCribeTopic(Topic);
            btn_start.BackColor = Color.Green;
        }

        /// <summary>
        /// 断开MQTT服务器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btn_stop_Click(object sender, EventArgs e)
        {
            await _MQTTHelper.DisconnectAsync_Client();
            btn_start.BackColor = Color.DarkCyan;
        }
          
        /// <summary>
        /// 订阅设备上线消息
        /// </summary>
        private void subscribe_dev_topic(string dev_type)
        {
            if (string.IsNullOrEmpty(dev_type))
            {
                MessageBox.Show("订阅设备类型不能为空！");
                return;
            }
            string type = "0";
            if (this.dev_type.Text == "巡检车")
                type = "0";
            else
                type = "1";
            string topic = "iot/" + type + "/online";
            _MQTTHelper.SubscribeAsync_Client(topic);
        }

        /// <summary>
        /// 订阅设备上线消息
        /// </summary>
        private void subscribe_info_topic(string dev_type)
        {
            if (string.IsNullOrEmpty(dev_type))
            {
                MessageBox.Show("订阅设备类型不能为空！");
                return;
            }
            string type = "0";
            if (this.dev_type.Text == "巡检车")
                type = "0";
            else
                type = "1";
            string topic = "iot/" + type + "/info";
            _MQTTHelper.SubscribeAsync_Client(topic);
        }

        /// <summary>
        /// 订阅设备上线消息
        /// </summary>
        private void subscribe_response_topic(string dev_type)
        {
            if (string.IsNullOrEmpty(dev_type))
            {
                MessageBox.Show("订阅设备类型不能为空！");
                return;
            }
            string type = this.dev_type.Text;
            string topic = "iot/" + type + "/response";
            _MQTTHelper.SubscribeAsync_Client(topic);
        }

        private async void PublishMessage(String Topic, String message)
        {
            bool retained = false;
            if (string.IsNullOrEmpty(Topic) || string.IsNullOrEmpty(Topic))
            {
                MessageBox.Show("Topic 不能为空！");
                return;
            }
            if(string.IsNullOrEmpty(message) || message.Equals(""))
            {
                message = "{}";
            }
            await _MQTTHelper.PublishAsync_Client(Topic, message, retained);
        }


        private void SubsCribeTopic(String Topic)
        {
            if (string.IsNullOrEmpty(Topic) || string.IsNullOrEmpty(Topic))
            {
                MessageBox.Show("订阅主题不能为空！");
                return;
            }
            _MQTTHelper.SubscribeAsync_Client(Topic);
        }

        private async void publish_bridge_cmd(string client_id, string cmd)
        {
            if (string.IsNullOrEmpty(client_id) || string.IsNullOrEmpty(cmd))
            {
                MessageBox.Show("订阅设备类型不能为空！");
                return;
            }
            string topic = "iot/bridge/" + cmd;
            var myObject = new { server_id = client_id, port_down = proxy_port.Text };
            string json = JsonConvert.SerializeObject(myObject);
            bool retained = false;
            await _MQTTHelper.PublishAsync_Client(topic, json, retained);
        }

        private void button_query_type_Click(object sender, EventArgs e)
        {
            comboBox_project.Items.Clear();
            dev_type.Items.Clear();
            online_dev_list.Items.Clear();
            DeviceList.Clear();
            String Topic = "";
            string type = "0";
            type = this.dev_type.Text;
            Topic = String.Format("iot/{0}/online", type);
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/{0}/info", type);
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/{0}/query", type);
            PublishMessage(Topic, "");
        }

        private void query_dev_Click(object sender, EventArgs e)
        {
            comboBox_project.Items.Clear();
            dev_type.Items.Clear();
            online_dev_list.Items.Clear();
            DeviceList.Clear();
            String Topic = "";
            string type = "0";
            type = this.dev_type.Text;
            Topic = String.Format("iot/devices/online" );
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/devices/info" );
            SubsCribeTopic(Topic);
            Topic = String.Format("iot/query");
            PublishMessage(Topic, "");
        }

        private void btn_clear_log_Click(object sender, EventArgs e)
        {
            this.textBoxLog.Clear();
        }

        private void btn_clear_list_Click(object sender, EventArgs e)
        {
            this.online_dev_list.Items.Clear();
        }

        /// <summary>
        /// 架线指令
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_open_line_Click(object sender, EventArgs e)
        {
            String Topic = "";
            BridgeConfig newConfig = new BridgeConfig();
            if (online_dev_list.Items.Count == 0)
            {
                Trace_log("暂无设备可连接.");
                return;
            }
            newConfig.client_id = client_id;
            newConfig.device_id = online_dev_list.SelectedItem.ToString();
            newConfig.bridge_ip = this.proxy_ip.Text;
            newConfig.bridge_port = int.Parse(this.proxy_port.Text);
            string newJsonString = JsonConvert.SerializeObject(newConfig);
            Topic = String.Format("iot/bridge/start");
            PublishMessage(Topic, newJsonString);
        }

        void StopBridge()
        { 
            String Topic = String.Format("iot/bridge/stop");
            String newJsonString = String.Format("{{\"client_id\":\"{0}\"}}", client_id);
            PublishMessage(Topic, newJsonString);
        }

        private void btn_close_line_Click(object sender, EventArgs e)
        {
            StopBridge();
        }

        private void btn_selected_Click(object sender, EventArgs e)
        {

        }

        private void button_get_project(object sender, EventArgs e)
        {
            button_list_dev_types();
            comboBox_project.Items.Clear();
            foreach(Device dev in DeviceList)
            {
                if (!comboBox_project.Items.Contains(dev.PJID))
                    comboBox_project.Items.Add(dev.PJID);
            }
            if (comboBox_project.Items.Count > 0)
                comboBox_project.SelectedIndex = 0;
        }

        private void button_list_dev_types()
        {
            dev_type.Items.Clear();
            foreach (Device dev in DeviceList)
            {
                if (!dev_type.Items.Contains(dev.DTYPE))
                    dev_type.Items.Add(dev.DTYPE);
            }
            if (dev_type.Items.Count > 0)
                dev_type.SelectedIndex = 0;
        }

        private void comboBox_project_SelectedIndexChanged(object sender, EventArgs e)
        {
            String text = comboBox_project.Text; 
            if (string.IsNullOrEmpty(text))
            {
                online_dev_list.Items.Clear();
                foreach (Device dev in DeviceList)
                { 
                    if (online_dev_list.Items.Contains(dev.DUID))
                    {
                        online_dev_list.Items.Add(dev.DUID);
                    }
                }
                if (online_dev_list.Items.Count > 0)
                    online_dev_list.SelectedIndex = 0;
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            StopBridge();
        }

        private void btn_close_all_line_Click(object sender, EventArgs e)
        {
            String Topic = String.Format("iot/bridge/clear");
            String newJsonString = String.Format("{{\"client_id\":\"{0}\"}}", client_id);
            PublishMessage(Topic, newJsonString);
        }
    }

    public class BridgeConfig
    {
        public string client_id { get; set; }
        public string device_id { get; set; }
        public string bridge_ip { get; set; }
        public int bridge_port { get; set; }
    }

    public class BridgeInfo
    {
        public int code;
        public string server_ip;
        public int server_port;
    }

    public class Device
    { 
        public string DTYPE;
        public string DUID;
        public string PJID;
    }
    public class DeviceInfo
    { 
        public string status;
        public long timestamp;
        public Device data;
    }

}